home *** CD-ROM | disk | FTP | other *** search
/ Just Call Me Internet / Just Call Me Internet.iso / prog / atari / c / nos042_s / ftpserv.c < prev    next >
C/C++ Source or Header  |  1994-09-16  |  17KB  |  702 lines

  1. /*
  2.     Internet FTP Server
  3.     Copyright 1991 Phil Karn, KA9Q
  4. */
  5.  
  6. /****************************************************************************
  7. *    $Id: ftpserv.c 1.3 94/02/02 14:38:06 ROOT_DOS Exp $
  8. *    01 Feb 94    1.2        GT    New sendfile () and recvfile () prototypes
  9. *
  10. *  Atari Version by David Nash - dnash@chaos.demon.co.uk
  11. *
  12. *      Allow access to any disk if ftpuser path is '/'
  13. *     Add CDUP command 
  14. ****************************************************************************/
  15.  
  16. #include <stdio.h>
  17. #include <ctype.h>
  18. #include <time.h>
  19. #ifdef ATARI
  20. #include <errno.h>     /* ST NOS - sys_errlist > strerror    */
  21. #include <sys/types.h>
  22. #include <sys/stat.h>
  23. #include <unistd.h>
  24. #endif
  25.  
  26. #ifdef    __TURBOC__
  27. #include <io.h>
  28. #include <dir.h>
  29. #endif
  30.  
  31. #include "global.h"
  32. #include "mbuf.h"
  33. #include "proc.h"
  34. #include "socket.h"
  35. #include "dirutil.h"
  36. #include "commands.h"
  37. #include "files.h"
  38. #include "ftp.h"
  39. #include "ftpserv.h"
  40.  
  41. static void __stdargs ftpserv __ARGS((int s,void *unused,void *p));
  42. static int pport __ARGS((struct sockaddr_in *sock,char *arg));
  43. static void ftplogin __ARGS((struct ftpserv *ftp,char *pass));
  44. static int sendit __ARGS((struct ftpserv *ftp,char *command,char *file));
  45. static int recvit __ARGS((struct ftpserv *ftp,char *command,char *file));
  46.  
  47. #ifdef ATARI
  48. int    statx(const char *path, struct stat *statbuf);
  49. #endif
  50.  
  51. /* Command table */
  52. static char *commands[] = {
  53.     "user",
  54.     "acct",
  55.     "pass",
  56.     "type",
  57.     "list",
  58.     "cwd",
  59.     "dele",
  60.     "name",
  61.     "quit",
  62.     "retr",
  63.     "stor",
  64.     "port",
  65.     "nlst",
  66.     "pwd",
  67.     "xpwd",            /* For compatibility with 4.2BSD */
  68.     "mkd ",
  69.     "xmkd",            /* For compatibility with 4.2BSD */
  70.     "xrmd",            /* For compatibility with 4.2BSD */
  71.     "rmd ",
  72.     "stru",
  73.     "mode",
  74.     "cdup",
  75.     NULLCHAR
  76. };
  77.  
  78. /* Response messages */
  79. static char banner[] = "220 %s FTP version %s ready at %s\n";
  80. static char badcmd[] = "500 Unknown command\n";
  81. static char binwarn[] = "100 Warning: type is ASCII and %s appears to be binary\n";
  82. static char unsupp[] = "500 Unsupported command or option\n";
  83. static char givepass[] = "331 Enter PASS command\n";
  84. static char giveanonpass[]="331 Enter Email address as password\n";
  85. static char logged[] = "230 Logged in\n";
  86. static char typeok[] = "200 Type %s OK\n";
  87. static char only8[] = "501 Only logical bytesize 8 supported\n";
  88. static char deleok[] = "250 File deleted\n";
  89. static char mkdok[] = "200 MKD ok\n";
  90. static char delefail[] = "550 Delete failed: %s\n";
  91. static char pwdmsg[] = "257 \"%s\" is current directory\n";
  92. static char badtype[] = "501 Unknown type \"%s\"\n";
  93. static char badport[] = "501 Bad port syntax\n";
  94. static char unimp[] = "502 Command not yet implemented\n";
  95. static char bye[] = "221 Goodbye!\n";
  96. static char nodir[] = "553 Can't read directory \"%s\": %s\n";
  97. static char cantopen[] = "550 Can't read file \"%s\": %s\n";
  98. static char sending[] = "150 Opening data connection for %s %s\n";
  99. static char cantmake[] = "553 Can't create \"%s\": %s\n";
  100. static char writerr[] = "552 Write error: %s\n";
  101. static char portok[] = "200 Port command okay\n";
  102. static char rxok[] = "226 File received OK\n";
  103. static char txok[] = "226 File sent OK\n";
  104. static char noperm[] = "550 Permission denied\n";
  105. static char noconn[] = "425 Data connection reset\n";
  106. static char lowmem[] = "421 System overloaded, try again later\n";
  107. static char notlog[] = "530 Please log in with USER and PASS\n";
  108. static char userfirst[] = "503 Login with USER first.\n";
  109. static char okay[] = "200 Ok\n";
  110.  
  111. static int Sftp = -1;    /* Prototype socket for service */
  112.  
  113. /* Start up FTP service */
  114. int
  115. ftpstart(argc,argv,p)
  116. int argc;
  117. char *argv[];
  118. void *p;
  119. {
  120.     struct sockaddr_in lsocket;
  121.     int s;
  122.  
  123.     if(Sftp != -1){
  124.         /* Already running! */
  125.         return 0;
  126.     }
  127.     psignal(Curproc,0);    /* Don't keep the parser waiting */
  128.     chname(Curproc,"FTP listener");
  129.  
  130.     lsocket.sin_family = AF_INET;
  131.     lsocket.sin_addr.s_addr = INADDR_ANY;
  132.     if(argc < 2)
  133.         lsocket.sin_port = IPPORT_FTP;
  134.     else
  135.         lsocket.sin_port = atoi(argv[1]);
  136.  
  137.     Sftp = socket(AF_INET,SOCK_STREAM,0);
  138.     bind(Sftp,(char *)&lsocket,sizeof(lsocket));
  139.     listen(Sftp,1);
  140.     for(;;){
  141.         if((s = accept(Sftp,NULLCHAR,(int *)NULL)) == -1)
  142.             break;    /* Service is shutting down */
  143.  
  144.         if(availmem() < Memthresh){
  145.             usprintf(s,lowmem);
  146.             shutdown(s,1);
  147.         } else {
  148.             /* Spawn a server */
  149.             newproc("ftpserv",2048,ftpserv,s,NULL,NULL,0);
  150.         }
  151.     }
  152.     return 0;
  153. }
  154. static void
  155. __stdargs ftpserv(s,unused,p)
  156. int s;    /* Socket with user connection */
  157. void *unused;
  158. void *p;
  159. {
  160.     struct ftpserv ftp;
  161.     char **cmdp,buf[512],*arg,*cp,*cp1,*file,*mode;
  162.     long t;
  163.     int cnt,i;
  164.     struct sockaddr_in socket;
  165.  
  166. #ifdef ATARI
  167.     struct stat statbuf;
  168. #endif    
  169.     
  170.     sockmode(s,SOCK_ASCII);
  171.     memset((char *)&ftp,0,sizeof(ftp));    /* Start with clear slate */
  172.     ftp.data = -1;
  173.  
  174.     sockowner(s,Curproc);        /* We own it now */
  175.     ftp.control = s;
  176.     /* Set default data port */
  177.     i = SOCKSIZE;
  178.     getpeername(s,(char *)&socket,&i);
  179.     socket.sin_port = IPPORT_FTPD;
  180.     ASSIGN(ftp.port,socket);
  181.  
  182.     log(s,"open FTP");
  183.     time(&t);
  184.     cp = ctime(&t);
  185.     if((cp1 = strchr(cp,'\n')) != NULLCHAR)
  186.         *cp1 = '\0';
  187.     usprintf(s,banner,Hostname,Version,cp);
  188. loop:    if((cnt = recvline(s,buf,sizeof(buf))) == -1){
  189.         /* He closed on us */
  190.         goto finish;
  191.     }
  192.     if(cnt == 0){
  193.         /* Can't be a legal FTP command */
  194.         usprintf(ftp.control,badcmd);
  195.         goto loop;
  196.     }    
  197.     rip(buf);
  198. #ifdef    UNIX
  199.     /* Translate first word to lower case */
  200.     for(cp = buf;*cp != ' ' && *cp != '\0';cp++)
  201.         *cp = tolower(*cp);
  202. #else
  203.     /* Translate entire buffer to lower case */
  204.     for(cp = buf;*cp != '\0';cp++)
  205.         *cp = tolower(*cp);
  206. #endif
  207.     /* Find command in table; if not present, return syntax error */
  208.     for(cmdp = commands;*cmdp != NULLCHAR;cmdp++)
  209.         if(strncmp(*cmdp,buf,strlen(*cmdp)) == 0)
  210.             break;
  211.     if(*cmdp == NULLCHAR){
  212.         usprintf(ftp.control,badcmd);
  213.         goto loop;
  214.     }
  215.     /* Allow only USER, PASS and QUIT before logging in */
  216.     if(ftp.cd == NULLCHAR || ftp.path == NULLCHAR){
  217.         switch(cmdp-commands){
  218.         case USER_CMD:
  219.         case PASS_CMD:
  220.         case QUIT_CMD:
  221.             break;
  222.         default:
  223.             usprintf(ftp.control,notlog);
  224.             goto loop;
  225.         }
  226.     }
  227.     arg = &buf[strlen(*cmdp)];
  228.     while(*arg == ' ')
  229.         arg++;
  230.  
  231.     /* Execute specific command */
  232.     switch(cmdp-commands){
  233.     case USER_CMD:
  234.         free(ftp.username);
  235.         ftp.username = strdup(arg);
  236.         if ((cp=userlookup(ftp.username,&cp1,NULLCHARP,NULLINT,NULL))!=NULLCHAR)
  237.         {
  238.             if (strcmp(cp1,"@")==0)
  239.                 usprintf(ftp.control,giveanonpass);
  240.             else
  241.                 usprintf(ftp.control,givepass);
  242.             free(cp);
  243.         }
  244.         else
  245.             usprintf(ftp.control,givepass);
  246.         break;
  247.     case TYPE_CMD:
  248.         switch(arg[0]){
  249.         case 'A':
  250.         case 'a':    /* Ascii */
  251.             ftp.type = ASCII_TYPE;
  252.             usprintf(ftp.control,typeok,arg);
  253.             break;
  254.         case 'l':
  255.         case 'L':
  256.             while(*arg != ' ' && *arg != '\0')
  257.                 arg++;
  258.             if(*arg == '\0' || *++arg != '8'){
  259.                 usprintf(ftp.control,only8);
  260.                 break;
  261.             }
  262.             ftp.type = LOGICAL_TYPE;
  263.             ftp.logbsize = 8;
  264.             usprintf(ftp.control,typeok,arg);
  265.             break;
  266.         case 'B':
  267.         case 'b':    /* Binary */
  268.         case 'I':
  269.         case 'i':    /* Image */
  270.             ftp.type = IMAGE_TYPE;
  271.             usprintf(ftp.control,typeok,arg);
  272.             break;
  273.         default:    /* Invalid */
  274.             usprintf(ftp.control,badtype,arg);
  275.             break;
  276.         }
  277.         break;
  278.     case QUIT_CMD:
  279.         usprintf(ftp.control,bye);
  280.         goto finish;
  281.     case RETR_CMD:
  282.         file = pathname(ftp.cd,arg);
  283.         switch(ftp.type){
  284.         case IMAGE_TYPE:
  285.         case LOGICAL_TYPE:
  286.             mode = READ_BINARY;
  287.             break;
  288.         case ASCII_TYPE:
  289.             mode = READ_TEXT;
  290.             break;
  291.         }
  292.         if(!permcheck(ftp.path,ftp.perms,RETR_CMD,file)){
  293.              usprintf(ftp.control,noperm);
  294.         } else if((ftp.fp = fopen(file,mode)) == NULLFILE){
  295.             usprintf(ftp.control,cantopen,file,strerror(errno));
  296.         } else {
  297.             log(ftp.control,"RETR %s",file);
  298.             if(ftp.type == ASCII_TYPE && isbinary(ftp.fp)){
  299.                 usprintf(ftp.control,binwarn,file);
  300.             }
  301.             sendit(&ftp,"RETR",file);
  302.         }        
  303.         free(file);
  304.         break;
  305.     case STOR_CMD:
  306.         file = pathname(ftp.cd,arg);
  307.         switch(ftp.type){
  308.         case IMAGE_TYPE:
  309.         case LOGICAL_TYPE:
  310.             mode = WRITE_BINARY;
  311.             break;
  312.         case ASCII_TYPE:
  313.             mode = WRITE_TEXT;
  314.             break;
  315.         }
  316.         if(!permcheck(ftp.path,ftp.perms,STOR_CMD,file)){
  317.              usprintf(ftp.control,noperm);
  318.         } else if((ftp.fp = fopen(file,mode)) == NULLFILE){
  319.             usprintf(ftp.control,cantmake,file,strerror(errno));
  320.         } else {
  321.             log(ftp.control,"STOR %s",file);
  322.             recvit(&ftp,"STOR",file);
  323.         }
  324.         free(file);
  325.         break;
  326.     case PORT_CMD:
  327.         if(pport(&ftp.port,arg) == -1){
  328.             usprintf(ftp.control,badport);
  329.         } else {
  330.             usprintf(ftp.control,portok);
  331.         }
  332.         break;
  333. #ifndef CPM
  334.     case LIST_CMD:
  335.         file = pathname(ftp.cd,arg);
  336.         if(!permcheck(ftp.path,ftp.perms,RETR_CMD,file)){
  337.              usprintf(ftp.control,noperm);
  338.         } else if((ftp.fp = dir(file,1)) == NULLFILE){
  339.             usprintf(ftp.control,nodir,file,strerror(errno));
  340.         } else {
  341.             sendit(&ftp,"LIST",file);
  342.         }
  343.         free(file);
  344.         break;
  345.     case NLST_CMD:
  346.         file = pathname(ftp.cd,arg);
  347.         if(!permcheck(ftp.path,ftp.perms,RETR_CMD,file)){
  348.              usprintf(ftp.control,noperm);
  349.         } else if((ftp.fp = dir(file,0)) == NULLFILE){
  350.             usprintf(ftp.control,nodir,file,strerror(errno));
  351.         } else {
  352.             sendit(&ftp,"NLST",file);
  353.         }
  354.         free(file);
  355.         break;
  356.     case CWD_CMD:
  357.     case CDUP_CMD:
  358.         if (*arg == '\0')
  359.             file = pathname(ftp.cd,"..");        /* CDUP    */
  360.         else
  361.             file = pathname(ftp.cd,arg);        /* CWD    */
  362.  
  363.         if(!permcheck(ftp.path,ftp.perms,RETR_CMD,file)){
  364.              usprintf(ftp.control,noperm);
  365.             free(file);
  366.             break;
  367.         }
  368.     
  369. #if defined(MSDOS) 
  370.         if(strcmp(file,"/") == 0 || access(file,0) == 0) {
  371.  
  372. #elif defined(ATARI)
  373.         if(statx(file, &statbuf) == 0 ||
  374.          (file[1] == ':' && file[2] == '\0')) {
  375.  
  376. #else
  377.         if(access(file,0) == 0)    {                /* See if it exists */
  378. #endif
  379.             /* Succeeded, record in control block */
  380.             free(ftp.cd);
  381.             ftp.cd = file;
  382.             usprintf(ftp.control, pwdmsg, file);
  383.         } else {
  384.             /* Failed, don't change anything */
  385.             usprintf(ftp.control,nodir,file,strerror(errno));
  386.             free(file);
  387.         }
  388.         break;
  389.     case XPWD_CMD:
  390.     case PWD_CMD:
  391.         usprintf(ftp.control,pwdmsg,ftp.cd);
  392.         break;
  393. #else
  394.     case LIST_CMD:
  395.     case NLST_CMD:
  396.     case CWD_CMD:
  397.     case CDUP_CMD:
  398.     case XPWD_CMD:
  399.     case PWD_CMD:
  400. #endif
  401.     case ACCT_CMD:        
  402.         usprintf(ftp.control,unimp);
  403.         break;
  404.     case DELE_CMD:
  405.         file = pathname(ftp.cd,arg);
  406.         if(!permcheck(ftp.path,ftp.perms,DELE_CMD,file)){
  407.              usprintf(ftp.control,noperm);
  408.         } else if(unlink(file) == 0){
  409.             log(ftp.control,"DELE %s",file);
  410.             usprintf(ftp.control,deleok);
  411.         } else {
  412.             usprintf(ftp.control,delefail,strerror(errno));
  413.         }
  414.         free(file);
  415.         break;
  416.     case PASS_CMD:
  417.         if(ftp.username == NULLCHAR)
  418.             usprintf(ftp.control,userfirst);
  419.         else
  420.             ftplogin(&ftp,arg);            
  421.         break;
  422. #ifndef    CPM
  423.     case XMKD_CMD:
  424.     case MKD_CMD:
  425.         file = pathname(ftp.cd,arg);
  426.         if(!permcheck(ftp.path,ftp.perms,MKD_CMD,file)){
  427.             usprintf(ftp.control,noperm);
  428. #ifdef    UNIX
  429.         } else if(mkdir(file,0777) == 0){
  430. #else
  431.         } else if(mkdir(file) == 0){
  432. #endif
  433.             log(ftp.control,"MKD %s",file);
  434.             usprintf(ftp.control,mkdok);
  435.         } else {
  436.             usprintf(ftp.control,cantmake,file,strerror(errno));
  437.         }
  438.         free(file);
  439.         break;
  440.     case XRMD_CMD:
  441.     case RMD_CMD:
  442.         file = pathname(ftp.cd,arg);
  443.         if(!permcheck(ftp.path,ftp.perms,RMD_CMD,file)){
  444.              usprintf(ftp.control,noperm);
  445.         } else if(rmdir(file) == 0){
  446.             log(ftp.control,"RMD %s",file);
  447.             usprintf(ftp.control,deleok);
  448.         } else {
  449.             usprintf(ftp.control,delefail,strerror(errno));
  450.         }
  451.         free(file);
  452.         break;
  453.     case STRU_CMD:
  454.         if(tolower(arg[0]) != 'f')
  455.             usprintf(ftp.control,unsupp);
  456.         else
  457.             usprintf(ftp.control,okay);
  458.         break;
  459.     case MODE_CMD:
  460.         if(tolower(arg[0]) != 's')
  461.             usprintf(ftp.control,unsupp);
  462.         else
  463.             usprintf(ftp.control,okay);
  464.         break;
  465.     }
  466. #endif
  467.     goto loop;
  468. finish:
  469.     log(ftp.control,"close FTP");
  470.     /* Clean up */
  471.     close_s(ftp.control);
  472.     if(ftp.data != -1)
  473.         close_s(ftp.data);
  474.     if(ftp.fp != NULLFILE)
  475.         fclose(ftp.fp);
  476.     free(ftp.username);
  477.     free(ftp.path);
  478.     free(ftp.cd);
  479. }
  480.  
  481. /* Shut down FTP server */
  482. int
  483. ftp0(argc,argv,p)
  484. int argc;
  485. char *argv[];
  486. void *p;
  487. {
  488.     close_s(Sftp);
  489.     Sftp = -1;
  490.     return 0;
  491. }
  492. static
  493. int
  494. pport(sock,arg)
  495. struct sockaddr_in *sock;
  496. char *arg;
  497. {
  498.     int32 n;
  499.     int i;
  500.  
  501.     n = 0;
  502.     for(i=0;i<4;i++){
  503.         n = atoi(arg) + (n << 8);
  504.         if((arg = strchr(arg,',')) == NULLCHAR)
  505.             return -1;
  506.         arg++;
  507.     }
  508.     sock->sin_addr.s_addr = n;
  509.     n = atoi(arg);
  510.     if((arg = strchr(arg,',')) == NULLCHAR)
  511.         return -1;
  512.     arg++;
  513.     n = atoi(arg) + (n << 8);
  514.     sock->sin_port = n;
  515.     return 0;
  516. }
  517.  
  518. /* Attempt to log in the user whose name is in ftp->username and password
  519.  * in pass
  520.  */
  521. static void
  522. ftplogin(ftp,pass)
  523. struct ftpserv *ftp;
  524. char *pass;
  525. {
  526.     char *path;
  527.     int anony = 0;
  528.  
  529.     path = mallocw(200);
  530.     if((ftp->perms = userlogin(ftp->username,pass,&path,200,&anony))
  531.        == -1){
  532.         usprintf(ftp->control,noperm);
  533.         free(path);
  534.         return;
  535.     }
  536.     /* Set up current directory and path prefix */
  537. #if    defined(AMIGAGONE)
  538.     ftp->cd = pathname("", path);
  539.     ftp->path = strdup(ftp->cd);
  540.     free(path);
  541. #else
  542.     ftp->cd = path;
  543.     ftp->path = strdup(path);
  544. #endif
  545.  
  546.     usprintf(ftp->control,logged);
  547.     if(!anony)
  548.         log(ftp->control,"%s logged in",ftp->username);
  549.     else
  550.         log(ftp->control,"%s logged in, ID %s",ftp->username,pass);
  551. }
  552.  
  553. #if defined(MSDOS) || defined(ATARI)
  554. /* Illegal characters in a DOS filename */
  555. static char badchars[] = "\"[]:|<>+=;,";
  556. #endif
  557.  
  558. /* Return 1 if the file operation is allowed, 0 otherwise */
  559. int
  560. permcheck(path,perms,op,file)
  561. char *path;
  562. int perms;
  563. int op;
  564. char *file;
  565. {
  566. #if defined(MSDOS) || defined(ATARI)
  567.     char *cp;
  568. #endif
  569.  
  570.     if(file == NULLCHAR || path == NULLCHAR)
  571.         return 0;    /* Probably hasn't logged in yet */
  572. #if defined(MSDOS) || defined(ATARI)
  573.     /* Check for characters illegal in MS-DOS file names */
  574.     for(cp = badchars;*cp != '\0';cp++){
  575.         if(strchr(file,*cp) != NULLCHAR && file[1] != ':')  /* check ':' DFN */
  576.             return 0;    
  577.     }
  578. #endif
  579. #ifndef MAC
  580.     /* The target file must be under the user's allowed search path */
  581.    /* allow any file if path is just '\' - DFN                     */
  582.     if(strncmp(file,path,strlen(path)) != 0)
  583.       if (strcmp(path, "\\") != 0 && strcmp(path, "/") != 0) {
  584.             return 0;
  585.         }
  586. #endif
  587.  
  588.     switch(op){
  589.     case RETR_CMD:
  590.         /* User must have permission to read files */
  591.          if(perms & FTP_READ)
  592.             return 1;
  593.         return 0;
  594.     case DELE_CMD:
  595.     case RMD_CMD:
  596.         /* User must have permission to (over)write files */
  597.         if(perms & FTP_WRITE)
  598.             return 1;
  599.         return 0;
  600.     case STOR_CMD:
  601.     case MKD_CMD:
  602.         /* User must have permission to (over)write files, or permission
  603.          * to create them if the file doesn't already exist
  604.          */
  605.         if(perms & FTP_WRITE)
  606.             return 1;
  607.         if(access(file,2) == -1 && (perms & FTP_CREATE))
  608.             return 1;
  609.         return 0;
  610.     }
  611.  
  612.     return 0;    /* "can't happen" -- keep lint happy */
  613. }
  614. static int
  615. sendit(ftp,command,file)
  616. struct ftpserv *ftp;
  617. char *command;
  618. char *file;
  619. {
  620.     long total;
  621.     struct sockaddr_in dport;
  622.  
  623.     ftp->data = socket(AF_INET,SOCK_STREAM,0);
  624.     dport.sin_family = AF_INET;
  625.     dport.sin_addr.s_addr = INADDR_ANY;
  626.     dport.sin_port = IPPORT_FTPD;
  627.     bind(ftp->data,(char *)&dport,SOCKSIZE);
  628.     usprintf(ftp->control,sending,command,file);
  629.     if(connect(ftp->data,(char *)&ftp->port,SOCKSIZE) == -1){
  630.         fclose(ftp->fp);
  631.         ftp->fp = NULLFILE;
  632.         close_s(ftp->data);
  633.         ftp->data = -1;
  634.         usprintf(ftp->control,noconn);
  635.         return -1;
  636.     }
  637.     /* Do the actual transfer */
  638.     total = sendfile(ftp->fp,ftp->data,ftp->type,0,0);
  639.  
  640.     if(total == -1){
  641.         /* An error occurred on the data connection */
  642.         usprintf(ftp->control,noconn);
  643.         shutdown(ftp->data,2);    /* Blow away data connection */
  644.     } else {
  645.         usprintf(ftp->control,txok);
  646.     }
  647.     fclose(ftp->fp);
  648.     ftp->fp = NULLFILE;
  649.     close_s(ftp->data);
  650.     ftp->data = -1;
  651.     if(total == -1)
  652.         return -1;
  653.     else
  654.         return 0;
  655. }
  656. static int
  657. recvit(ftp,command,file)
  658. struct ftpserv *ftp;
  659. char *command;
  660. char *file;
  661. {
  662.     struct sockaddr_in dport;
  663.     long total;
  664.  
  665.     ftp->data = socket(AF_INET,SOCK_STREAM,0);
  666.     dport.sin_family = AF_INET;
  667.     dport.sin_addr.s_addr = INADDR_ANY;
  668.     dport.sin_port = IPPORT_FTPD;
  669.     bind(ftp->data,(char *)&dport,SOCKSIZE);
  670.     usprintf(ftp->control,sending,command,file);
  671.     if(connect(ftp->data,(char *)&ftp->port,SOCKSIZE) == -1){
  672.         fclose(ftp->fp);
  673.         ftp->fp = NULLFILE;
  674.         close_s(ftp->data);
  675.         ftp->data = -1;
  676.         usprintf(ftp->control,noconn);
  677.         return -1;
  678.     }
  679.     total = recvfile(ftp->fp,ftp->data,ftp->type,0,0);
  680.  
  681. #ifdef    CPM
  682.     if(ftp->type == ASCII_TYPE)
  683.         putc(CTLZ,ftp->fp);
  684. #endif
  685.     if(total == -1) {
  686.         /* An error occurred while writing the file */
  687.         usprintf(ftp->control,writerr,strerror(errno));
  688.         shutdown(ftp->data,2);    /* Blow it away */
  689.     } else {
  690.         usprintf(ftp->control,rxok);
  691.         close_s(ftp->data);
  692.     }
  693.     ftp->data = -1;
  694.     fclose(ftp->fp);
  695.     ftp->fp = NULLFILE;
  696.     if(total == -1)
  697.         return -1;
  698.     else
  699.         return 0;
  700. }
  701.  
  702.